#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<conio.h>
#include<time.h>
#include"TESTKISS.c"

/* POINTS TO REMEMBER: (1) TO CREATE A FLOAT BETWEEN 0-1 USE ALEA(0.0,1.0) - BUT CHANGE THE TYPE TO DOUBLE 
                       (2) FOR INTEGER - USE ALEA_INTEGER(A,B) */

/* REMEMBER: (1) AM COMMENTING RANDOM_NUMBER() - I.E FOR FLOAT VALUE GENERATION 
             (2) AND AM GOING TO DO AWAY WITH RAND() - I.E FOR INTEGER VALUE GENERATION 

SO CHANGE ACCORDINGLY */

int i,j,index_min_particle,iteration=0;
double c1=2.0,c2=2.0,c3=2.0;
double f1,f2,f3,f4,f;

void calculate_d();
void calculate_pdash();
void create_pheromone();
// changes

//int t_current= 0;
double w;


int k=100;
int ability_level=3;
int expected_learning_targets[10];
int l_time_course=20;
int u_time_course=30;

int m=10;
int n=200;
int difficulty_level[200];
int r[200][10];
int time_material[200];



struct position
{
 double position_value;
 int position_vector[200];
};

struct pheromone
{
	struct position pos;
	float p;
	float ROI;
	float d[20];
	float pdash[20];
};

//-------------------------------------------------------------------------------------------------------------------------

struct node;
typedef struct node *ptr;
typedef ptr posit;
typedef ptr plist;

struct node
{
	struct pheromone *pp;
	posit next;
	posit prev;
};

plist l;

//------------------------------------------------------------------------------------------------------------------------



struct particle
{
 struct position current_pos;
 double velocity[200];
 struct position pbest;
 struct pheromone tp;
};

struct swarm
{
 struct position gbest;
 struct particle p[20];
}s;


/*int max(int a,int b)
{
    if(a>b) return a;
    else return b;
}*/

/*float random_number()
{
   float r_temp;
   //time_t t1;
	//srand((unsigned) &t1);
  
   r_temp= (float) (rand() /(float) RAND_MAX);
   return(r_temp);
}*/


void initialize_problem_variables()
{
	int i,j;
	FILE *fp1;
	fp1=fopen("var.txt","w");
	/*learners intitialization*/
	fprintf(fp1,"expected learning targets\n");
	for(i=0;i<m;i++)
	{
                    	expected_learning_targets[i]=alea_integer(0,32768) % 2;
                    	fprintf(fp1,"%d\t",expected_learning_targets[i]);
    }

	/*material initialization*/
	fprintf(fp1,"\n\n difficulty level\n");
	for(i=0;i<n;i++)
	{
		difficulty_level[i]=1+alea_integer(0,32768) % 5;
		fprintf(fp1,"lm-%d----%d\n",i,difficulty_level[i]);
    }
    fprintf(fp1,"\n\ncovered learning concept\n");
	for(i=0;i<n;i++)
	{
         fprintf(fp1,"lm===%d====",i);
		for(j=0;j<m;j++)
		{
                        r[i][j]=alea_integer(0,32768) % 2;
                        fprintf(fp1,"%d",r[i][j]);
        }
        fprintf(fp1,"\n");
  }
   fprintf(fp1,"\nlearning material\n");
	for(i=0;i<n;i++)
	{
	 time_material[i]=1+(alea_integer(0,32768) % 5);
	 fprintf(fp1,"lmtime-%d----%d\n",i,time_material[i]);
	}

}

double fit1(int par)
{
	int i,j;
	double denum=0.0;
	double nume=0.0;
	for(i=0;i<n;i++)
		denum+=s.p[par].current_pos.position_vector[i];

	for(i=0;i<m;i++)
	{
		for(j=0;j<n;j++)
		{
		nume+=s.p[par].current_pos.position_vector[j]*abs(r[j][i]-expected_learning_targets[i]);
		}
	}
	
	return(nume/denum);
}

double fit2(int par)
{
	int i;
	double nume=0.0,denum=0.0;
	for(i=0;i<n;i++)
		denum+=s.p[par].current_pos.position_vector[i];
	for(i=0;i<n;i++)
	{
		nume+= s.p[par].current_pos.position_vector[i]*abs(difficulty_level[i]-ability_level);
	}
	return(nume/denum);
}

int fit3(int par)
{
	int c1=0;
    int i,c2,c3;
    for(i=0;i<n;i++)
		{c1+=time_material[i]* s.p[par].current_pos.position_vector[i];}
	
	c2=max((l_time_course-c1),0);
	c3=max(0,(c1-u_time_course));
	return(c2+c3);
}

double fit4(int par)
{
	double c1,c2=0.0,c3=0.0,nume=0.0,denum=0.0;
	int i,j;
	for(i=0;i<m;i++)
		for(j=0;j<n;j++)
			nume+= s.p[par].current_pos.position_vector[j]*r[j][i];
	for(i=0;i<m;i++)
			denum+= expected_learning_targets[i];
  
   
	c1=(nume/denum);

     
	for(i=0;i<m;i++)
	{
        c2=0.0;            
		for(j=0;j<n;j++)
			c2+= (double)(s.p[par].current_pos.position_vector[j]*r[j][i]);
	
		
		c3+=expected_learning_targets[i]*abs(c2-c1);
	
	
	}
	
	return c3;
}

void fitness_value(int i,FILE *fp)
{

	f1=fit1(i);
	f2=fit2(i);
	f3=(double)fit3(i);
	f4=fit4(i);
	f=(0.4*f1)+(0.4*f2)+(0.1*f3)+(0.1*f4);
	s.p[i].current_pos.position_value=f;
	fprintf(fp,"iter:%d par%d f1:%f f2:%f f3:%f f4:%f f5:%f\n",iteration,i,f1,f2,f3,f4,f);
}

double change()
{
	//double component1;
	double w1;
	//component1=(((1000-iteration)*(0.5))/1000);
	w1= 0.5 + alea(0.0,1.0)/2.0;
	return (w1);

}

void calculate_velocity(int i,int j)
{
  
  double component1,component2,component3;
  double r1,r2,r3;
  r1=alea(0.0,1.0);
  r2=alea(0.0,1.0);
  r3=alea(0.0,1.0);
  w=change();
  component1=(c1* r1 * (s.p[i].pbest.position_vector[j] - s.p[i].current_pos.position_vector[j]));
  component2=(c2* r2 * (s.gbest.position_vector[j] - s.p[i].current_pos.position_vector[j]));
component3=(c3* r3 * (s.p[i].tp.pos.position_vector[j]-s.p[i].current_pos.position_vector[j]));
///printf("%f\n",component3);
  s.p[i].velocity[j] = (w * s.p[i].velocity[j]) +(component1+component2);//+component3);
}

void sigmoid_scaling(int i,int j)
{
   s.p[i].velocity[j] = 1 / (10*(1+exp(-(s.p[i].velocity[j])) ));
}

void pbest()
{
  for(i=0;i<20;i++)
  {
     if(s.p[i].current_pos.position_value< s.p[i].pbest.position_value)
     {
      s.p[i].pbest.position_value = s.p[i].current_pos.position_value;

      for(j=0;j<n;j++)
      {
       s.p[i].pbest.position_vector[j]= s.p[i].current_pos.position_vector[j];
      }
	  create_pheromone(i);
     }
  }
}

void gbest()
{

 index_min_particle=0;

 for(i=1;i<20;i++)
 {
  if(s.p[i].pbest.position_value < s.p[index_min_particle].pbest.position_value)
  index_min_particle=i;
 }

 s.gbest.position_value = s.p[index_min_particle].pbest.position_value;
 for(j=0;j<n;j++)
 {
  s.gbest.position_vector[j] = s.p[index_min_particle].pbest.position_vector[j];
 }
 //++iteration;
}




//----------------------------------------------------------------------------------------------------
void create_pheromone(int k)
{
	int y;
	posit t;
	t=l;
	while(t->next!=NULL)
	{
		t=t->next;
	}


	t->next=malloc(sizeof(struct node));
	t->next->pp=malloc(sizeof(struct pheromone));
	t->next->next=NULL;
	t->next->pp->p=1.0;
	t->next->pp->ROI=1.0;
	t->next->pp->pos.position_value=s.p[k].current_pos.position_value;
	//printf("\n%f\n",s.p[5].current_pos.position_value);
	//printf("\n %f\n",t->next->pp->pos.position_value);
	for(y=0;y<n;y++)
	{
	
		t->next->pp->pos.position_vector[y]=s.p[k].current_pos.position_vector[y];
		//printf("%d",t->next->pp->pos.position_vector[i]);
		//printf("%d",s.p[k].current_pos.position_vector[i]);
	}
	calculate_d();
	calculate_pdash();
}

	
	
void calculate_d()
{
	posit t;
	int y,z;
	float x,a,b,c;
	t=l->next;
	//printf("%f\n\n\n",t->pp->pos.position_value);
	while(t!=NULL)
	{
		
		//printf("\n%f\n",t->pp->pos.position_value);
		for(y=0;y<20;y++)
		{
			a=0;
			b=0;
			for(z=0;z<n;z++)
			{

				b=(t->pp->pos.position_vector[z]-s.p[y].current_pos.position_vector[z])*0.1;
				a=a+(b*b);

			}
			//printf("value of a is %f\n",a);
			t->pp->d[y]=sqrt(a);
			//printf("%f\n",t->pp->d[i]);
		}
		t=t->next;
	}
}

void calculate_pdash()
{
	posit t;
	int y;
	float x,a,b,c;
	t=l->next;
	while(t!=NULL)
	{

		for(y=0;y<20;y++)
		{
			t->pp->pdash[y]=(1-t->pp->d[y])*t->pp->p;
		//	printf("%f\n\n",t->pp->pdash[j]);
		}
		t=t->next;
	}

}

void decay_p()
{

	posit t;
	int i,j;
	float x,a,b,c;
	t=l->next;
	while(t!=NULL)
	{
		t->pp->p*=0.95;
		t->pp->ROI*=0.95;
		t=t->next;
	}
	calculate_d();
	calculate_pdash();
}


void find_tp()
{
	posit t;
	int y,z,minp;
	float min=100;
	calculate_d();
	calculate_pdash();
	for(y=0;y<20;y++)
	{
		t=l->next;
	
		while(t!=NULL)
		{
			if(t->pp->pdash[y]<min)
			{
				min=t->pp->pdash[y];
				s.p[y].tp.pos.position_value=t->pp->pos.position_value;

				for(z=0;z<n;z++)
				{
					s.p[y].tp.pos.position_vector[z]=t->pp->pos.position_vector[z];
				}
				//s.p[i].tp=&(t->pp);
				//printf("%f\n",s.p[y].tp.pos.position_value);
			}
			t=t->next;
		}
	}
}

void decay_vel()
{
	int z,x;
	
	for(z=0;z<20;z++)
	{
		for(x=0;x<n;x++)
		{

			s.p[z].velocity[x] = s.p[z].velocity[x] * 0.95;
		}
	}
}




//---------------------------------------------------------------------------------
int  main()
{
	int y;
  int nos,k,ctr1=0,ctr2=0;
  double r_temp;
  FILE *fp1,*fp,*fp2,*fp3,*fp4;
  l=malloc(sizeof(struct node));
  l->prev=NULL;
  l->next=NULL;
  //time_t t;
  
  //srand((unsigned) &t);
  
  initialize_problem_variables();
  fp1=fopen("particles.txt","w");
  fp=fopen("fitness.txt","w");
  fp2=fopen("velo.txt","w");
  fp3=fopen("par.txt","w");
  fp4=fopen("gbest.txt","w");
  
  for(i=0;i<20;i++)
  {
  
  fprintf(fp2,"\n\npar===%d===",i);

   for(j=0;j<n;j++)
   {
    //s.p[i].current_pos.position_vector[j]=rand()%2;
	
    s.p[i].velocity[j]=alea(0.0,1.0);
    fprintf(fp2,"%f",s.p[i].velocity[j]);
        
   }
   
  }

  for(i=0;i<20;i++)
  {
    nos=4+(alea_integer(0,32768)%27);
    for(j=0;j<nos;j++)
    {
      k=(alea_integer(0,32768)%200);
      if(s.p[i].current_pos.position_vector[k]==1)
      {
       nos++;
      }
      else
      s.p[i].current_pos.position_vector[k]=1;
    }
  }
  for(i=0;i<20;i++)
  {
                  fprintf(fp1,"par===%d===",i);
                  ctr1=0;
                  for(j=0;j<n;j++)
                  {if(s.p[i].current_pos.position_vector[j])
		          ctr1++;
                                  fprintf(fp1,"%d",s.p[i].current_pos.position_vector[j]);
                                  }
                  fprintf(fp1,"no1's:%d\n",ctr1);
  }
  for(i=0;i<20;i++)
  {
  
   fitness_value(i,fp);

   fprintf(fp1,"par%d===%f\n",i,s.p[i].current_pos.position_value);
  }

  for(i=0;i<20;i++)
  {
   s.p[i].pbest.position_value = s.p[i].current_pos.position_value;

   for(j=0;j<n;j++)
   {
    s.p[i].pbest.position_vector[j] = s.p[i].current_pos.position_vector[j];
   }
  }

 gbest();

 //initial release of pheromones

for(y=0;y<10;y++)
{

		m=alea_integer(0,32768) % 20;
	create_pheromone(m);
}
 find_tp();


 

 
 
 printf("%f\t\t%d\n",s.gbest.position_value, iteration);
 fprintf(fp4,"%f\t\t%d\n",s.gbest.position_value, iteration);

getch();
 while(iteration < 2000)
 {
	 decay_vel();
  
   decay_p();
   find_tp();
	 ++iteration;
  fprintf(fp,"\n\niteration:%d\n",iteration);
   for(i=0;i<20;i++)
   {
     for(j=0;j<n;j++)
     {
      calculate_velocity(i,j);
      sigmoid_scaling(i,j);
     }
    }

   for(i=0;i<20;i++)
   {
     for(j=0;j<n;j++)
     {
       r_temp=alea(0.0,1.0);
       if(r_temp < s.p[i].velocity[j])
		s.p[i].current_pos.position_vector[j]=1;
       else
		s.p[i].current_pos.position_vector[j]=0;
     }
    }

    for(i=0;i<20;i++)
    {
      fitness_value(i,fp);
    }

    pbest();
    gbest();
    
	fprintf(fp3,"\niterations::%d\n",iteration);
    for(i=0;i<20;i++){
					ctr2=0;
                   fprintf(fp3,"\nparticle::%d\n",i);
                  for(j=0;j<n;j++)
				  {            fprintf(fp3,"%d",s.p[i].current_pos.position_vector[j]);
								if(s.p[i].current_pos.position_vector[j])
										ctr2++;
				  }
				  fprintf(fp3,"no1's::%d\n",ctr2);
 
	}              
	printf("%f\t\t%d\n",s.gbest.position_value,iteration);
	fprintf(fp4,"%f\t\t%d\n",s.gbest.position_value,iteration);
	
 }
 
 
 getch();
 

}

